

let sqlite3 = require('sqlite3').verbose();
let _ = require('underscore');
let G = require('./config');

//
function isArrayOrObjectOrFunction(val){
    return _.isArray(val) || _.isObject(val) || _.isFunction(val);
}

function getSqlKVArray(obj){
    let lstSk = [];
    let lstSv = [];

    // 对obj的字段进行检查
    let keys = Object.keys(obj);
    for(let i = 0,len = keys.length; i < len; ++i){
        let k = keys[i];
        if(isArrayOrObjectOrFunction(obj[k])){
            throw new Error('obj[k] 是一个 数组 或者 函数 或者对象');
            continue;
        }

        lstSk.push(k);
        lstSv.push(obj[k]);
    }
    return {
        k: lstSk,
        v: lstSv
    };
}

// API
var mydb = {
    db:null,
    sqlArr:[],
    defaultPrimaryKeyId:'_kid'
};

// 创建/初始化 数据库
mydb.initDb = function(dbfile){
    this.db = new sqlite3.Database(dbfile);
};

mydb.closeDb = function(){
    if(this.db){
        this.db.close();
    }
};

//  mydb.update = function(sql,cb){
//     this.db.run(sql,function (err) {
//         if(err){
//             throw new Error('mydb error.' + (err.message || err));
//         }
//         G.log('操作成功!');
//         if(cb){
//             cb();
//         }
//     });
// };


/**
 * 插入
 * 删除
 * 更新
 * 创建表格语句
 * @type {function(*=): Promise<unknown>}
 */
mydb.insert = mydb.delete = mydb.update = mydb.createTable = function(sql){
    let self = this;
    return new Promise((resolve, reject) => {
        self.db.run(sql,(err)=>{
            if(err){
                reject(err);
            } else{
                resolve();
            }
        });
    });
};

// 删除表格
mydb.dropTable = function(tableName){
    let self  = this;
    return new Promise((resolve, reject) => {
        self.db.run(`drop table ${tableName}`,err=>{
            if(err){
                reject(err);
            }else{
                resolve();
            }
        })
    });
};

// mydb.insert = mydb.delete = function(sql){
//     let self = this;
//     return new Promise((resolve, reject) => {
//         self.db.run(sql,err=>{
//            if(err){
//                reject(err);
//            } else{
//                resolve();
//            }
//         });
//     });
// };


// 新插入一行后,可以返回刚插入行的id
mydb.getLastInsertRowId = function(){
  let self = this;
  return new Promise((resolve, reject) => {
      let sql = `SELECT max(_kid) as kid from ${G.Table_Info}`;
     self.db.get(sql,(err,row)=>{
         if(err){
             reject(err);
         } else{
             if(row){
                 resolve(row.kid);
             }else{
                 resolve(-1);
             }
         }
     });
  });
};




// 查询一条信息
mydb.queryItem = function(sql){
    let self = this;
    return new Promise((resolve, reject) => {
        self.db.get(sql,(err,row)=>{
            if(err){
                reject(err);
            }else{
                resolve(row);
            }
        });
    });
};

// 查所有
mydb.queryAll = function(sql){
    let self = this;
    return new Promise((resolve, reject) => {
        self.db.all(sql,(err,rows)=>{
            if(err){
                reject(err);
            }else{
                resolve(rows);
            }
        });
    });
};


//------------------
// 构建查询语句的sql
mydb.buildInsertSql = function(tableName){
    this.sqlArr.length = 0;
    this.sqlArr.push('insert into ' + tableName);
    return this;
};
mydb.values = function(obj){

    if(this.sqlArr.length !== 1){
        throw  new Error('this.sqlArr.length 应该等于 1');
    }

    let kvObj = getSqlKVArray(obj);
    let lstSk = kvObj.k;
    let lstSv = kvObj.v;

    this.sqlArr.push('(');

    for(let i = 0,len = lstSk.length; i < len; ++i){
        this.sqlArr.push(lstSk[i]);
        if(i !== len - 1){
            this.sqlArr.push(',');
        }else{
            this.sqlArr.push(')');
        }
    }

    this.sqlArr.push('values');
    this.sqlArr.push('(');

    for(let i = 0, len = lstSv.length; i < len; ++i){
        if(_.isString(lstSv[i])){
            this.sqlArr.push('"' + lstSv[i] + '"');
        }else if(_.isNumber(lstSv[i])){
            this.sqlArr.push(lstSv[i]);
        }else{
            throw new Error('暂时只支持字符串和number类型');
        }

        if(i !== len - 1){
            this.sqlArr.push(',');
        }else{
            this.sqlArr.push(')');
        }
    }
    return this;
};


// 构造一个查询语句
mydb.buildQuerySql = function(tableName){
    this.sqlArr.length = 0;
    this.sqlArr.push('select * from ' + tableName);
    return this;
};

// delete语句链式调用,但是不支持嵌套.
mydb.buildDeleteSql = function(tableName){
   this.sqlArr.length = 0;
   this.sqlArr.push('delete from ' + tableName);
   return this;
};


mydb.sql = function(){
    return this.sqlArr.join(' ');
};


// 构造一个更新语句
mydb.buildUpdateSql = function(tableName){
    this.sqlArr.length = 0;
    this.sqlArr.push('update ' + tableName + ' set');
    return this;
};

mydb.set = function(expr){
    if(this.sqlArr.length > 1){
        this.sqlArr.push(',');
    }
    this.sqlArr.push(expr);
    return this;
};

mydb.where = function(cond){
    this.sqlArr.push('where');
    this.sqlArr.push(cond);
    return this;
};


// 构造一条 create 语句
mydb.buildTableSql = function(tableName){
    this.sqlArr.length = 0;
    this.sqlArr.push('create table if not exists ' + tableName + '(');
    return this;
};

// 包含一个主键为 _kid 自动自增的字段
mydb.autoPrimaryKey = function(){
    if(this.sqlArr.length !== 1){
        throw  new Error('this.sqlArr.length 应该等于 1');
    }
    this.sqlArr.push(this.defaultPrimaryKeyId + ' integer primary key autoincrement,');
    return this;
};

// 指定主键
mydb.primaryKey = function(keyName,keyType){
    if(this.sqlArr.length !== 1){
        throw new Error('this.sqlArr.length 应该等于 1');
    }
    this.sqlArr.push(`${keyName} ${keyType} primary key,`);
    return this;
};

mydb.keys = function(keyArr){
    for(let i = 0,len = keyArr.length; i < len; ++i){
        if(keyArr[i].split(' ').length < 2){
            throw  new Error('需要为 '+ keyArr[i] + ' 指定数据类型');
        }
        this.sqlArr.push(keyArr[i]);
        if(i !== len - 1){
            this.sqlArr.push(',');
        }
    }
    this.sqlArr.push(')');
    return this;
};




module.exports = mydb;
